﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RaisingStudio.Data.Common.Expressions
{
    public class Parser
    {
        private ParseLevel parseLevel;
        public ParseLevel ParseLevel
        {
            get { return parseLevel; }
            set { parseLevel = value; }
        }

        private SourceCode sourceCode;
        public SourceCode SourceCode
        {
            get { return sourceCode; }
            private set { sourceCode = value; }
        }

        public Parser(string source)
        {
            this.SourceCode = new SourceCode();
            this.SourceCode.SourceArray = new List<string>(new string[] { source });
        }

        public Parser(List<string> source)
        {
            this.SourceCode = new SourceCode();
            this.SourceCode.SourceArray = source;
        }

        public List<Expression> Parse()
        {
            List<Expression> expressions = new List<Expression>();
            try
            {
                IScanner scanner = GetScanner();
                SourceLocation tokenBegin, tokenEnd;
                TokenType tokenType = scanner.ReadToken(out tokenBegin, out tokenEnd);
                while (tokenType != TokenType.NONE && tokenType != TokenType.EOF)
                {
                    switch (tokenType)
                    {
                        case TokenType.CHARACTER_LITERAL:
                            {
                                CharacterLiteral characterLiteral = new CharacterLiteral();
                                characterLiteral.Begin = tokenBegin;
                                characterLiteral.End = tokenEnd;
                                // set value, for debug.
                                //characterLiteral.Value = this.SourceCode.Contents.Substring(characterLiteral.Begin.Position, characterLiteral.End.Position - characterLiteral.Begin.Position);
                                expressions.Add(characterLiteral);
                                break;
                            }
                        case TokenType.STRING_LITERAL:
                        case TokenType.VERBATIM_STRING_LITERAL:
                            {
                                StringLiteral stringLiteral = new StringLiteral();
                                stringLiteral.Begin = tokenBegin;
                                stringLiteral.End = tokenEnd;
                                // set value, for debug.
                                //stringLiteral.Value = this.SourceCode.Contents.Substring(stringLiteral.Begin.Position, stringLiteral.End.Position - stringLiteral.Begin.Position);
                                expressions.Add(stringLiteral);
                                break;
                            }
                    }
                    tokenType = scanner.ReadToken(out tokenBegin, out tokenEnd);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
            return expressions;
        }

        private IScanner GetScanner()
        {
            IScanner scanner = null;
            switch (ParseLevel)
            {
                case ParseLevel.Character:
                    {
                        scanner = new CharacterScanner(this.SourceCode);
                        break;
                    }
                case ParseLevel.String:
                    {
                        scanner = new StringScanner(this.SourceCode);
                        break;
                    }
                case ParseLevel.Expression:
                    {
                        scanner = new ExpressionScanner(this.SourceCode);
                        break;
                    }
                default:
                    {
                        scanner = new ExpressionScanner(this.SourceCode);
                        break;
                    }
            }
            return scanner;
        }
    }
}
